package errorx

import (
	"gitee.com/zackeus/go-boot/common/constants/codes"
	gozeroErr "gitee.com/zackeus/go-zero/core/errorx"
	"gitee.com/zackeus/goutil/errorx"
	rpccodes "google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

/*************************************************************
 * helper func for error
 *************************************************************/

// IsDataNoExist 判断是否为数据不存在异常
func IsDataNoExist(err error) bool {
	/* 获取 CauseErr */
	causeErr := Cause(err)

	if e, ok := causeErr.(ErrorR); ok {
		/* 自定义异常 */
		return e.Code() == codes.NoExist
	}
	if e, ok := status.FromError(causeErr); ok {
		/* grpc 异常 */
		return e.Code() == rpccodes.DataLoss || e.Code() == rpccodes.NotFound
	}
	return false
}

// Wrap returns an error that wraps err with given message.
func Wrap(err error, message string) error {
	return gozeroErr.Wrap(err, message)
}

// Wrapf returns an error that wraps err with given format and args.
func Wrapf(err error, format string, args ...any) error {
	return gozeroErr.Wrapf(err, format, args...)
}

// Cause returns the first cause error by call err.Unwrap().
// Otherwise, will returns current error.
func Cause(err error) error {
	if err == nil {
		return nil
	}

	for err != nil {
		cause, ok := err.(interface {
			Unwrap() error
		})
		if !ok {
			break
		}
		err = cause.Unwrap()
	}
	return err
}

// In checks if the given err is one of errs.
func In(err error, errs ...error) bool {
	return gozeroErr.In(err, errs...)
}

// CauseErrDesc 获取最终错误描述信息
func CauseErrDesc(err error) string {
	/* 获取 CauseErr */
	causeErr := Cause(err)
	if e, ok := causeErr.(errorx.ErrorR); ok {
		/* 自定义CodeError */
		return e.Error()
	} else if s, ok := status.FromError(causeErr); ok {
		/* grpc err错误 */
		return s.Message()
	}

	return causeErr.Error()
}
